package wechat

import (
	"context"

	v1 "caas-platform-payment/api/wechat/v1"
	"caas-platform-payment/internal/consts"
	"caas-platform-payment/internal/dao"
	"caas-platform-payment/internal/model/entity"

	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/wechatpay-apiv3/wechatpay-go/core"
	"github.com/wechatpay-apiv3/wechatpay-go/core/option"
	"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
	"github.com/wechatpay-apiv3/wechatpay-go/utils"
)

func (c *ControllerV1) Refund(ctx context.Context, req *v1.RefundReq) (res *v1.RefundRes, err error) {
	tenantCode := ctx.Value(consts.TokenClaims.TenantCode).(string)
	// 读取商户信息
	cls := dao.PayChannel.Columns()
	if req.AppId == "" || req.OutTradeNo == "" || req.TotalFee == 0 {
		l.Error(ctx, req)
		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "参数错误")
	}
	ch := &entity.PayChannel{}
	err = dao.PayChannel.Ctx(ctx).Where(cls.TenantCode, tenantCode).Where(cls.AppId, req.AppId).Where(cls.ChannelName, consts.PayChannels[0].Name).Scan(ch)
	if err != nil || ch.Id == 0 {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.MerchantNotFound)
	}
	// 加载私钥
	privateKey, err := utils.LoadPrivateKey(ch.PrivateKey)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.LoadPrivateKeyFailed)
	}
	opts := []core.ClientOption{
		option.WithWechatPayAutoAuthCipher(ch.MerchantId, ch.MerchantCertSerialNumber, privateKey, ch.MerchantApiKey),
	}
	client, err := core.NewClient(ctx, opts...)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.WechatClientInitFailed)
	}
	svc := refunddomestic.RefundsApiService{Client: client}
	resp, result, err := svc.Create(ctx, refunddomestic.CreateRequest{
		OutTradeNo:  &req.OutTradeNo,
		OutRefundNo: &req.OutTradeNo,
		Amount: &refunddomestic.AmountReq{
			Total:    &req.TotalFee,
			Currency: core.String("CNY"),
		},
		NotifyUrl: &ch.RefundNotifyUrl,
	})
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.WechatRefundFailed)
	}
	if result.Response.StatusCode != 200 {
		l.Error(ctx, result.Response)
		return nil, gerror.NewCode(consts.WechatRefundFailed)
	}
	return &v1.RefundRes{Status: (*string)(resp.Status)}, nil
}
